#include "Channel.h"
#include "EventLoop.h"
#include "Logger.h"


#include <sys/epoll.h>


const int Channel::kNoneEvent = 0;
const int Channel::kReadEvent = EPOLLIN | EPOLLPRI;
const int Channel::kWriteEvent = EPOLLOUT;

// EventLoop : ChannelList Poller
Channel::Channel(EventLoop *loop, int fd)
                : m_loop(loop), m_fd(fd), m_events(0),  m_revents(0), m_index(-1), m_tied(false)
{
}

// fd得到poller通知之后，就进行对应事件的回调处理
void Channel::handleEvent(Timestamp receiveTime)
{
    // 检测回调的对象是否存活
    if (m_tied) {
        std::shared_ptr<void> guard = m_tie.lock();
        if (guard) {
            handleEventWithGuard(receiveTime);
        }
    } else {
        handleEventWithGuard(receiveTime);
    }
}

// 当一个TcpConnetion新连接创建的时候，TcpConnetion => Channel
void Channel::tie(const std::shared_ptr<void> &obj)
{
    m_tie = obj;
    m_tied = true;
}

/*
 * 当改变Channel所封装的fd的events事件后，update负责在poller里面更改fd相应的事件  通过epoll_ctl 
 * EventLoop -> ChannelList Poller
*/
void Channel::update()
{
    // 通过channel所属的EventLoop调用poller对应的方法，改变fd的events事件在Poller中的状态（注册fd的events事件）
    m_loop->updateChannel(this);
}

// 根据poller通知Channel发生的具体事件，进行具体的回调操作
void Channel::handleEventWithGuard(Timestamp receiveTime)
{
    LOG_INFO("Channel handleEvent revents : %d \n", m_revents);
    if ( (m_revents & EPOLLHUP) && !(m_revents & EPOLLIN) ) {
        if (m_closeCallback) {
            m_closeCallback();
        }
    }

    if (m_revents & EPOLLERR) {
        if (m_errorCallback) {
            m_errorCallback();
        }
    }

    if (m_revents & (EPOLLIN | EPOLLPRI)) {
        if (m_readCallback) {
            m_readCallback(receiveTime);
        }
    }

    if (m_revents & EPOLLOUT) {
        if (m_writeCallback) {
            m_writeCallback();
        }
    }
}

// 在Channel所属的EventLoop中，把当前的Channel删除
void Channel::remove()
{
    m_loop->removeChannel(this);
}

